/**
 * @file TEST_diagnostic.c
 * @author Linquan  
 * @brief 
 * @version 1.0
 * @date 2024-05-11
 * 
 * @copyright Copyright (c) 2024
 * @note 
 * 
 *       ！！！诊断点的“诊断间隔时间” 大小，需要大于等于 
 *              “诊断框架任务执行的间隔时间（DIAGNOSIC_PERIOD_MS）“ ！！！
 * 
 *      1、在头文件中设置 诊断间隔时间、诊断通过持续时间，诊断失败持续时间。
 *      
 *      2、本文件测试内容：当前通过时间计数为20,失败通过时间为20.
 *          TEST_count计数器不断累加，在累加超过20时，输出诊断通过。诊断通过时的操作
 *          计数器继续累加，累加超过24,开始判断为故障，
 *          故障后，持续计20个数，TEST_count达到44,输出诊断失败，进行失败时的操作，删除节点。
 *          完成 诊断节点功能测试。
 * 
 *      3、 诊断模块除了不断检查关键电路状态，还可以 用来做非阻塞超时处理：
 *             场景： 发送的信号，需要较长时间后才能得到反馈，但最长不超过5秒。
 *              设置诊断节点：检测周期为100ms，设置 检测通过时间为100ms，即检测到一次反馈就认为检测通过
 *                          检测失败事件为5000ms（5s），持续5秒没有检测到反馈，就认为失败。  
 *              发送信号后，添加该节点到诊断链表中。          
 *              在5秒内得到反馈，则诊断通过，发送 “收到反馈“事件 并删除该诊断节点。
 *              在5秒内没有得到反馈，则诊断失败，发送 “反馈超时”事件，并删除该节点。
 * 
 *      4、 该模块还可以作为 定时任务控制 使用：
 *              场景：想启动某个泵，持续运行10秒。
 *              设置诊断节点属性：
*                     诊断周期100ms；设置诊断函数 强制返回诊断通过（返回0），
*                     设置通过的持续时间为10秒（10000/100ms 次）。 设置失败持续时间100m（失败一次即可执行确认函数）。
*                     设置确认函数 将启动的泵关闭，并删除该节点。
 *              在启动泵后，添加该节点到诊断链表。
 *              泵会持续运行10秒，之后诊断通过，执行确认函数，将泵关闭，删除节点。
 *              如果想在运行的10秒中间停止，可以在诊断函数中加入条件，判为诊断失败，
 *              即可执行确认函数，停止泵，删除节点。
 * 
 */


#include "app_config.h"

#if TEST_DIAGNOSTIC

#include "TEST_diagnostic.h"


#define  OVERVOLTAGE_24   	24

STR_DIAG_CFG_NODE stDiag24VHFaultCfg; /* 声明一个 诊断节点 */
static uint8_t  TEST_count = 0;


/**
 * 24v诊断过压
 * 1 = 有故障， 0 = 无故障 
 * 24V过压诊断，如果出现超出正常范围的电压，返回1，如果正常返回0
*/
ENU_DETCT_FLAG  powerNode24VHDiag(void)
{
    TEST_count++;
    CYAN_PRINT("TEST_diagnostic count is %d \n",TEST_count);
	
    if (TEST_count > OVERVOLTAGE_24)
	{	
    	RED_PRINT("TEST_diagnostic count is big than 24, is fault\n");
        return FLAG_FAIL;  // 有故障
    } 
	    
	return FLAG_PASS;
}



/**
 * 24v过压确认
 * confirmed: 确认状态，1=诊断未通过失败  、 0 = 诊断通过 成功
 * 1 = 有故障， 0 = 无故障 
 * 24V过压确认， 诊断通过或失败 需要执行的操作
*/
void powerNode24VHConfirm(ENU_DETCT_FLAG  confirmed)
{
     if ( FLAG_FAIL == confirmed ) 
	{
        BLUE_PRINT("TEST_diagnostic is fail. delete this point \n");
        // 诊断未通过失败，执行相应操作       	   
        DiagDltNode(&stDiag24VHFaultCfg);
    } 	
	 else if (FLAG_PASS == confirmed  )   
	{
        YELLOW_PRINT("TEST_diagnostic is pass. continue check this point \n");
        // 诊断通过成功，执行相应操作	
    }	
}


/**
 * @brief 配置诊断节点
 *          配置诊断周期、通过持续
 * 
 */
STR_DIAG_CFG_NODE stDiag24VHFaultCfg = {
	.stDTCStatus = 0,
    .usPeriod = POWER_24VH_FAULT_PERIOD,                /* 周期 */
    .usPassLimit = POWER_24VH_FAULT_PASS_LIMIT,         /* 通过次数 */
    .usFailedLimit = POWER_24VH_FAULT_FAILED_LIMIT,     /* 失败次数 */ 
    .sCounter = 0,                                      /* 故障计数器 */
    .irfDiagFunction = powerNode24VHDiag,               /* 故障诊断函数 */
    .irfFaultConfirm = powerNode24VHConfirm,            /* 故障确认函数 */
	
};


/**
 * 诊断初始化
 * 将诊断的各个节点，添加到诊断列表里
*/
void TEST_diagPowerNodeInit()
{
    DiagAddNode(&stDiag24VHFaultCfg);
}
EXPORT_Lv6_APP_INIT(TEST_diagPowerNodeInit, NULL);


/**
 * @brief 诊断调度，在task任务链表里，定时执行
 * 
 */
int task_TEST_diagnostic(task_param_t* args)
{
	 DiagMainProcess();
	return MS_( DIAGNOSIC_PERIOD_MS) ; 
}


/**
 * @brief 按照export 结构体的函数指针 建立函数.添加到任务链表
 * 
 * @param ptr 
 */
void Add_task_TEST_diagnostic(void* ptr)
{
    Master_task_add(&task_TEST_diagnostic, 0);
}
EXPORT_Lv6_APP_SINGLE(Add_task_TEST_diagnostic,NULL);



#endif


















